package com.sbtr.business.publishtask.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sbtr.business.publishtask.entity.PlatformPredictTask;
import com.sbtr.business.publishtask.mapper.PlatformPredictTaskMapper;
import com.sbtr.business.publishtask.service.IPlatformPredictTaskService;
import com.sbtr.business.trainingserver.service.impl.TrainingServerServiceImpl;
import com.sbtr.common.PageDto;
import com.sbtr.constant.ColumnConstant;
import com.sbtr.exception.BizException;
import com.sbtr.open.publishtask.dto.*;
import com.sbtr.open.trainingserver.dto.TrainingServerDto;
import com.sbtr.util.BeanCopyUtils;
import com.sbtr.util.PageDtoUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Transactional
@Service
public class PlatformPredictTaskServiceImpl extends ServiceImpl<PlatformPredictTaskMapper, PlatformPredictTask>
        implements IPlatformPredictTaskService {
    private static final Logger logger = LoggerFactory.getLogger(PlatformPredictTaskServiceImpl.class);

    @Value("${ocr.config.ip}")
    private String Ip;

    @Value("${oss.config.uploadPath}")
    private String uploadPath;

    @Value("${oss.config.httpPath}")
    private String httpPath;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private TrainingServerServiceImpl serverService;

    @Override
    public PlatformPredictTaskDto findById(Long id) {
        // TODO Auto-generated method stub
        PlatformPredictTask task = getById(id);
        if (task != null) {
            return BeanCopyUtils.copyProperties(task, PlatformPredictTaskDto.class);
        }

        return null;
    }

    @Override
    public PlatformPredictTaskDto save(PlatformPredictTaskDto dto) {
        // TODO Auto-generated method stub
        PlatformPredictTask platformPredictTask = BeanCopyUtils.copyProperties(dto, PlatformPredictTask.class);
        saveOrUpdate(platformPredictTask);
        dto.setId(platformPredictTask.getId());
        return dto;
    }


    /**
     * 判断文件大小
     *
     * @param len  文件长度
     * @param size 限制大小
     * @param unit 限制单位（B,K,M,G）
     * @return
     */
    public boolean checkFileSize(long len, int size, String unit) {
//        long len = file.length();
        double fileSize = 0;
        if ("B".equals(unit.toUpperCase())) {
            fileSize = (double) len;
        } else if ("K".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1024;
        } else if ("M".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1048576;
        } else if ("G".equals(unit.toUpperCase())) {
            fileSize = (double) len / 1073741824;
        }
        if (fileSize > size) {
            return true;
        }
        return false;
    }

    @Override
    public PageDto<PlatformPredictTaskDto> search(PlatformPredictSearchDto pro) {

        IPage<PlatformPredictTask> page = new Page<>();
        page.setSize(pro.getPageSize());
        page.setCurrent(pro.getPage());
        QueryWrapper<PlatformPredictTask> wrapper = new QueryWrapper<>();


        if (org.apache.commons.lang3.StringUtils.isNotEmpty(pro.getCreater())) {
            wrapper.eq(ColumnConstant.CREATER, pro.getCreater());
        }

        if (StringUtils.isNotEmpty(pro.getTaskName())) {
            wrapper.like("task_name", pro.getTaskName());
        }

        if (null != pro.getStatus() && !pro.getStatus().isEmpty()) {
            wrapper.in(ColumnConstant.STATUS, pro.getStatus());
        }


        if (null != pro.getTaskTypes() && !pro.getTaskTypes().isEmpty()) {
            wrapper.in(ColumnConstant.TASK_TYPE, pro.getTaskTypes());
        }

//		if (null != pro.getCreateTime()) {
//			Date createTimeTo = pro.getCreateTime(); //取时间
//			Calendar calendar = new GregorianCalendar();
//			calendar.setTime(createTimeTo);
//			calendar.add(calendar.DATE,1); //把日期往后增加一天,整数  往后推,负数往前移动
//			createTimeTo=calendar.getTime(); //这个时间就是日期往后推一天的结果
//			wrapper.between(ColumnConstant.CREATE_TIME, pro.getCreateTime(), createTimeTo);
//		}
//
//		if (null != pro.getEndTime()) {
//			Date createTimeTo = pro.getEndTime(); //取时间
//			Calendar calendar = new GregorianCalendar();
//			calendar.setTime(createTimeTo);
//			calendar.add(calendar.DATE,1); //把日期往后增加一天,整数  往后推,负数往前移动
//			createTimeTo=calendar.getTime(); //这个时间就是日期往后推一天的结果
//			wrapper.between("end_time", pro.getEndTime(), createTimeTo);
//		}

        if (null != pro.getCreateTime() && null != pro.getEndTime()) {
            wrapper.between(ColumnConstant.CREATE_TIME, pro.getCreateTime(), pro.getEndTime());
        }

        wrapper.orderByDesc("id");
        page = page(page, wrapper);
        PageDto<PlatformPredictTaskDto> pageDto = PageDtoUtils.getPageDtoByIPage(page, PlatformPredictTaskDto.class);
        return pageDto;
    }

    @Override
    public PredictOcrDto startTaskSingle(String filePath
    ) {
        // 查询所有在线的GPU服务器
        List<TrainingServerDto> serverDtos = serverService.getList(TrainingServerDto.TRAINING_SERVER_STATUS_ONLINE,
                TrainingServerDto.SERVER_TYPE_OCR_PUBLISH, null);
        Assert.isTrue(serverDtos != null && !serverDtos.isEmpty(), "没有可用的服务器");
        Ip = serverDtos.get(0).getIp();

        String url = "http://" + Ip + "/abilityApi/predictOne";
        logger.info("启动训练任务请求地址:{} ", url);
        HttpHeaders headers = this.initRestTemplateHeader();
        // 请求体
        Map<String, Object> postParameters = new HashMap<>();
        postParameters.put("taskType", "1001");
        postParameters.put("modelName", "Ocr");
        postParameters.put("filePath", filePath);

        String jsonBody = JSON.toJSONString(postParameters);
        logger.info("启动训练任务参数: {}", jsonBody);
        HttpEntity<String> r = new HttpEntity<>(jsonBody, headers);

        ResponseEntity<String> postForEntity = null;
        try {
            postForEntity = restTemplate.postForEntity(url, r, String.class);
        } catch (Exception e) {
            logger.error(Ip + " 调用ocr单条异常, [" + e.getMessage() + "]", e);
        }
        // 返回结果
        String body = postForEntity.getBody();
        JSONObject jsObj = JSONObject.parseObject(body);
        if (jsObj.getInteger("code") != null && 200 == jsObj.getInteger("code")) {
            JSONArray result = jsObj.getJSONArray("data");
            String resultPath = result.getString(0);
            JSONArray predictData = result.getJSONArray(1);
            if (uploadPath.contains("\\\\")) {//双反斜杠  换  单反斜杠
                uploadPath = uploadPath.replace("\\\\", "\\");
            }
            resultPath = org.apache.commons.lang3.StringUtils.substringAfterLast(resultPath, uploadPath);
            PredictOcrDto predictOcrDto = new PredictOcrDto();
            predictOcrDto.setImgPath(httpPath + resultPath);
            predictOcrDto.setPredictData(predictData);
            return predictOcrDto;
        } else {
            Integer code = jsObj.getInteger("code") != null ? jsObj.getInteger("code") : 0;
            String msg = org.apache.commons.lang3.StringUtils.isNotBlank(jsObj.getString("msg")) ? jsObj.getString("msg") : "";
            String data = org.apache.commons.lang3.StringUtils.isNotBlank(jsObj.getString("data")) ? jsObj.getString("data") : "";
            logger.error("状态码: " + code + ", msg: " + msg + ", data: " + data);
            throw new BizException(msg);
        }
    }


    @Override
    public PredictNlpOneDto startLanguageSingle(String languageType,String comment
    ) {
        // 查询所有在线的GPU服务器
        List<TrainingServerDto> serverDtos = serverService.getList(TrainingServerDto.TRAINING_SERVER_STATUS_ONLINE,
                TrainingServerDto.SERVER_TYPE_OCR_PUBLISH, null);
        Assert.isTrue(serverDtos != null && !serverDtos.isEmpty(), "没有可用的服务器");
        Ip = serverDtos.get(0).getIp();

        String url = "http://" + Ip + "/abilityApi/predictOne";
        logger.info("启动训练任务请求地址:{} ", url);
        HttpHeaders headers = this.initRestTemplateHeader();
        // 请求体
        Map<String, Object> postParameters = new HashMap<>();
        postParameters.put("taskType", "2000");
        postParameters.put("modelName", "nlp");
        postParameters.put("comment", comment);
        postParameters.put("languageType", languageType);

        String jsonBody = JSON.toJSONString(postParameters);
        logger.info("启动训练任务参数: {}", jsonBody);
        HttpEntity<String> r = new HttpEntity<>(jsonBody, headers);

        ResponseEntity<String> postForEntity = null;
        try {
            postForEntity = restTemplate.postForEntity(url, r, String.class);
        } catch (Exception e) {
            logger.error(Ip + " 调用nlp单条异常, [" + e.getMessage() + "]", e);
        }
        // 返回结果
        String body = postForEntity.getBody();
        JSONObject jsObj = JSONObject.parseObject(body);
        if (jsObj.getInteger("code") != null && 200 == jsObj.getInteger("code")) {
            JSONObject result = JSONObject.parseObject(jsObj.getString("data"));

//			result.get()
//			JSONArray predictData = result.getJSONArray(1);
            PredictNlpOneDto predictDto = new PredictNlpOneDto();
            predictDto.setPredictData(result);
            return predictDto;
        } else {
            Integer code = jsObj.getInteger("code") != null ? jsObj.getInteger("code") : 0;
            String msg = org.apache.commons.lang3.StringUtils.isNotBlank(jsObj.getString("msg")) ? jsObj.getString("msg") : "";
            String data = org.apache.commons.lang3.StringUtils.isNotBlank(jsObj.getString("data")) ? jsObj.getString("data") : "";
            logger.error("状态码: " + code + ", msg: " + msg + ", data: " + data);
            throw new BizException(msg);
        }
    }


    @Override
    public boolean ocrMulti(Long id
    ) {
        // 查询所有在线的GPU服务器
        List<TrainingServerDto> serverDtos = serverService.getList(TrainingServerDto.TRAINING_SERVER_STATUS_ONLINE,
                TrainingServerDto.SERVER_TYPE_OCR_PUBLISH, null);
        Assert.isTrue(serverDtos != null && !serverDtos.isEmpty(), "没有可用的服务器");
        Ip = serverDtos.get(0).getIp();

        String url = "http://" + Ip + "/abilityApi/predictBig";
        logger.info("启动训练任务请求地址:{} ", url);
        HttpHeaders headers = this.initRestTemplateHeader();
        // 请求体
        Map<String, Object> postParameters = new HashMap<>();
        postParameters.put("predictId", id);

        String jsonBody = JSON.toJSONString(postParameters);
        logger.info("启动训练任务参数: {}", jsonBody);
        HttpEntity<String> r = new HttpEntity<>(jsonBody, headers);
        ResponseEntity<String> postForEntity = restTemplate.postForEntity(url, r, String.class);

        // 返回结果
        String body = postForEntity.getBody();
        JSONObject jsObj = JSONObject.parseObject(body);
        if (jsObj.getInteger("code") != null && 200 == jsObj.getInteger("code")) {
            return true;
        } else {
            Integer code = jsObj.getInteger("code") != null ? jsObj.getInteger("code") : 0;
            String data = org.apache.commons.lang3.StringUtils.isNotBlank(jsObj.getString("data")) ? jsObj.getString("data") : "";
            logger.error("状态码: " + code + ", data: " + data);
        }
        return false;
    }


    @Override
    public boolean languageMulti(PlatformPredictTaskDto dto) {
        // 查询所有在线的GPU服务器
        List<TrainingServerDto> serverDtos = serverService.getList(TrainingServerDto.TRAINING_SERVER_STATUS_ONLINE,
                TrainingServerDto.SERVER_TYPE_OCR_PUBLISH, null);
        Assert.isTrue(serverDtos != null && !serverDtos.isEmpty(), "没有可用的服务器");
        Ip = serverDtos.get(0).getIp();

        String url = "http://" + Ip + "/abilityApi/predictBig";
        logger.info("启动训练任务请求地址:{} ", url);
        HttpHeaders headers = this.initRestTemplateHeader();
        // 请求体
        Map<String, Object> postParameters = new HashMap<>();
        postParameters.put("predictId", dto.getId());
        postParameters.put("languageType", dto.getLanguageType());
        postParameters.put("taskType", dto.getTaskType());

        String jsonBody = JSON.toJSONString(postParameters);
        logger.info("启动训练任务参数: {}", jsonBody);
        HttpEntity<String> r = new HttpEntity<>(jsonBody, headers);
        ResponseEntity<String> postForEntity = restTemplate.postForEntity(url, r, String.class);

        // 返回结果
        String body = postForEntity.getBody();
        JSONObject jsObj = JSONObject.parseObject(body);
        if (jsObj.getInteger("code") != null && 200 == jsObj.getInteger("code")) {
            return true;
        } else {
            Integer code = jsObj.getInteger("code") != null ? jsObj.getInteger("code") : 0;
            String data = org.apache.commons.lang3.StringUtils.isNotBlank(jsObj.getString("data")) ? jsObj.getString("data") : "";
            logger.error("状态码: " + code + ", data: " + data);
        }
        return false;
    }


    private HttpHeaders initRestTemplateHeader() {

        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);// 请求类型
        headers.add("Access-Control-Allow-Origin", "*");
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());// 接收类型
        return headers;
    }


    @Override
    public String getResultUrl(Long id) {
        // TODO Auto-generated method stub
        PlatformPredictTask task = getById(id);
        if (task != null) {
            if (PublishPredictTaskDto.PREDICT_COMPLETE.equals(task.getStatus())) {
                if (StringUtils.isNotBlank(task.getResultFile())) {

                    String bucketName = task.getResultFile().substring(0, task.getResultFile().indexOf("/"));
                    String objectName = task.getResultFile().substring(task.getResultFile().indexOf("/") + 1, task.getResultFile().length());
                    try {
                        return null;
                    } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                    }
                }
            }
        }
        return null;
    }


}
